﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace LambdaDemo.ConsoleApp.SerializeDemo
{
    public class SerializeUtility
    {
        public void XMLSerialize()
        {
            Person c = new Person();
            c.Courses = new Course[2];
            c.Courses[0] = new Course("英语", "交流工具");
            c.Courses[1] = new Course("数学", "自然科学");
            c.Emp = new Employee();
            c.Emp.EmpId = 100;
            c.Emp.EmpName = "T";
            XmlSerializer xs = new XmlSerializer(typeof(Person));
            //xs.UnknownElement += new XmlElementEventHandler(xs_UnknownElement);
            Stream stream = new FileStream("d:\\cyj.XML", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
            xs.Serialize(stream, c);

            stream.Close();


        }

        public void XMLDeserialize()
        {
            XmlSerializer xs = new XmlSerializer(typeof(Person));
            xs.UnknownElement += new XmlElementEventHandler(xs_UnknownElement);
            Stream stream = new FileStream("d:\\cyj.XML", FileMode.Open, FileAccess.Read, FileShare.Read);
            Person p = xs.Deserialize(stream) as Person;

            Console.WriteLine(p.Name);
            Console.WriteLine(p.Age.ToString());
            Console.WriteLine(p.Courses[0].Name);
            Console.WriteLine(p.Courses[0].Description);
            Console.WriteLine(p.Courses[1].Name);
            Console.WriteLine(p.Courses[1].Description);
            stream.Close();
        }

        void xs_UnknownElement(object sender, XmlElementEventArgs e)
        {
            var a = e;
        }

        public void Binary()
        {
            // Create a new TestSimpleObject object.
            TestSimpleObject obj = new TestSimpleObject();

            Console.WriteLine("\n Before serialization the object contains: ");
            obj.Print();

            // Open a file and serialize the object into binary format.
            Stream stream = File.Open("DataFile.dat", FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();

            try
            {
                formatter.Serialize(stream, obj);

                // Print the object again to see the effect of the 
                //OnSerializedAttribute.
                Console.WriteLine("\n After serialization the object contains: ");
                obj.Print();

                // Set the original variable to null.
                obj = null;
                stream.Close();

                // Open the file "DataFile.dat" and deserialize the object from it.
                stream = File.Open("DataFile.dat", FileMode.Open);

                // Deserialize the object from the data file.
                obj = (TestSimpleObject)formatter.Deserialize(stream);

                Console.WriteLine("\n After deserialization the object contains: ");
                obj.Print();
                Console.ReadLine();
            }
            catch (SerializationException se)
            {
                Console.WriteLine("Failed to serialize. Reason: " + se.Message);
                throw;
            }
            catch (Exception exc)
            {
                Console.WriteLine("An exception occurred. Reason: " + exc.Message);
                throw;
            }
            finally
            {
                stream.Close();
                obj = null;
                formatter = null;
            }

        }
    }
    [Serializable]
    public class Person : IXmlSerializable
    {
        private string name;
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public Employee Emp
        {
            get;
            set;
        }

        public string Sex;
        public int Age = 31;
        public Course[] Courses;

        public Person()
        {
        }

        #region IXmlSerializable 成员

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {

        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            //writer.WriteStartDocument(false);
            
            writer.Settings.ConformanceLevel = System.Xml.ConformanceLevel.Document;
            writer.WriteStartElement("name");
            writer.WriteValue(this.Name);
            writer.WriteEndElement();
            //writer.WriteEndDocument();
        }

        #endregion
    }
    [Serializable]
    public class Course
    {
        public string Name;
        [XmlIgnore]
        public string Description;
        public Course()
        {
        }
        public Course(string name, string description)
        {
            Name = name;
            Description = description;
        }
    }
    [Serializable]
    public class Employee : ISerializable
    {
        public int EmpId = 100;
        public string EmpName = "刘德华";
        [NonSerialized]
        public string NoSerialString = "NoSerialString-Test";
        public Employee()
        {
        }

        public Employee(SerializationInfo info, StreamingContext ctxt)
        {
            EmpId = (int)info.GetValue("EmployeeId", typeof(int));
            EmpName = (String)info.GetValue("EmployeeName", typeof(string));
            //NoSerialString = (String)info.GetValue("EmployeeString",typeof(string));
        }

        [OnDeserialized]
        public void OnDeserialized(StreamingContext context)
        {
            // Called once the deserialization process is complete.
            EmpId = 333;
        }



        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("EmployeeId", EmpId);
            info.AddValue("EmployeeName", EmpName);
            //info.AddValue("EmployeeString", NoSerialString);

        }
    }
    [Serializable()]
    public class TestSimpleObject
    {
        // This member is serialized and deserialized with no change.
        public int member1;

        // The value of this field is set and reset during and 
        // after serialization.
        private string member2;

        // This field is not serialized. The OnDeserializedAttribute 
        // is used to set the member value after serialization.
        [NonSerialized()]
        public string member3;

        // This field is set to null, but populated after deserialization.
        private string member4;

        // Constructor for the class.
        public TestSimpleObject()
        {
            member1 = 11;
            member2 = "Hello World!";
            member3 = "This is a nonserialized value";
            member4 = null;
        }

        public void Print()
        {
            Console.WriteLine("member1 = '{0}'", member1);
            Console.WriteLine("member2 = '{0}'", member2);
            Console.WriteLine("member3 = '{0}'", member3);
            Console.WriteLine("member4 = '{0}'", member4);
        }

        [OnSerializing()]
        internal void OnSerializingMethod(StreamingContext context)
        {
            member2 = "This value went into the data file during serialization.";
        }

        [OnSerialized()]
        internal void OnSerializedMethod(StreamingContext context)
        {
            member2 = "This value was reset after serialization.";
        }

        [OnDeserializing()]
        internal void OnDeserializingMethod(StreamingContext context)
        {
            member3 = "This value was set during deserialization";
        }

        [OnDeserialized()]
        internal void OnDeserializedMethod(StreamingContext context)
        {
            member4 = "This value was set after deserialization.";
        }
    }

}
